using OdinSerializer;
using SerializationUtility = OdinSerializer.SerializationUtility;
using System.IO;
using UnityEngine;
using DA.AnimGraph;
using System;
using UnityEditor;
using System.Collections.Generic;

namespace DA.AnimGraph.Editor {

    /// <summary>
    /// 文件handle
    /// </summary>
    internal class AGAAssetHandle {
        AnimGraphArchiveAsset agaAsset;
        AGA_Root agaRootInternal;
        public string savePath;
        public string publishPath;

        public uint formatVersion => agaRoot.formatVersion;
        AGA_Root agaRoot {
            get {
                if (agaRootInternal == null) {
                    byte[] dataBytes = System.Text.Encoding.UTF8.GetBytes(agaAsset.archiveData);
                    agaRootInternal = SerializationUtility.DeserializeValue<AGA_Root>(dataBytes, DataFormat.JSON);
                }
                return agaRootInternal;
            }
            set => agaRootInternal = value;
        }

        internal AUID uuid => agaRoot.uuid;

        public static AGAAssetHandle Create() {
            var asset = ScriptableObject.CreateInstance<AnimGraphArchiveAsset>();
            var handle = new AGAAssetHandle() {
                agaAsset = asset,
                agaRootInternal = new(),
                savePath = null,
                publishPath = null
            };
            return handle;
        }

        public static AGAAssetHandle Open(string path) {
            if (string.IsNullOrEmpty(path)) {
                throw new Exception($"路径为空: ({path})");
            }

            var asset = AssetDatabase.LoadAssetAtPath<AnimGraphArchiveAsset>(path);
            if (asset == null) {
                throw new Exception($"无法加载指定文件: {path}");
            }
            byte[] dataBytes = System.Text.Encoding.UTF8.GetBytes(asset.archiveData);
            var agaRoot = SerializationUtility.DeserializeValue<AGA_Root>(dataBytes, DataFormat.JSON);
            var handle = new AGAAssetHandle() {
                agaAsset = asset,
                agaRootInternal = agaRoot,
                savePath = path,
                publishPath = asset.publishPath,
            };
            return handle;
        }

        // 浅打开，不反序列化那大堆数据
        public static AGAAssetHandle ShallowOpen(string path) {
            if (string.IsNullOrEmpty(path)) {
                D.L($"无法打开文件: {path}");
                return null;
            }
            var asset = AssetDatabase.LoadAssetAtPath<AnimGraphArchiveAsset>(path);
            var handle = new AGAAssetHandle() {
                agaAsset = asset,
                savePath = path,
                publishPath = asset.publishPath,
            };
            return handle;
        }

        private AGAAssetHandle() { }

        public void Save() {
            if (CheckSavePath()) {
                ReloadSOUuid();
                agaAsset.publishPath = publishPath;
                var archiveBytes = SerializeArchive();
                var json = System.Text.Encoding.UTF8.GetString(archiveBytes);
                agaAsset.archiveData = json;

                if (null == AssetDatabase.LoadAssetAtPath<AnimGraphArchiveAsset>(savePath)) {
                    AssetDatabase.CreateAsset(agaAsset, savePath);
                } else {
                    EditorUtility.SetDirty(agaAsset);
                    AssetDatabase.SaveAssets();
                }
                AssetDatabase.ScheduleRefresh();
            }
        }

        // 没有在使用了
        public void Publish(AnimGraphPublishAsset.Timeline[] timelines) {
            if (CheckPublishPath()) {
                // 保存导出路径
                agaAsset.publishPath = publishPath;
                EditorUtility.SetDirty(agaAsset);

                if (timelines == null) {
                    var tm = new TimelineManager(agaAsset.timelineData);
                    timelines = tm.Publish();
                }

                var publish = AGAPublisher.Export(agaRoot, agaAsset.resources, timelines);
                var publishBytes = SerializePublish(publish);
                File.WriteAllBytes(GetFullPublishPath("agp"), publishBytes);
                AssetDatabase.ScheduleRefresh();
            }
        }
        public AnimGraphPublishAsset ExportToAGPAsset(AnimGraphPublishAsset.Timeline[] timelines) {
            var agpAsset = AGAPublisher.Export(agaRoot, agaAsset.resources, timelines);
            return agpAsset;
        }
        public void ExportDry(AnimGraphPublishAsset.Timeline[] timelines) {
            if (CheckPublishPath()) {
                // 保存导出路径
                agaAsset.publishPath = publishPath;
                EditorUtility.SetDirty(agaAsset);

                var agp = AGAPublisher.Export(agaRoot, agaAsset.resources, timelines);
                using var writter = new BinaryDataBufferWriter();
                writter.WriteAGP(agp);
                var bytes = writter.GetBuffer();
                File.WriteAllBytes(GetFullPublishPath("agd"), bytes);

                // 同时导出agr文件
                if (AGEGlobal.GetInstance().setting.settingObject.exportResourcesWhenExport) {
                    var resRefPath = GetFullPublishPath("agr", "asset");
                    var oldAsset = AssetDatabase.LoadAssetAtPath<AnimGraphResourcesReferenceAsset>(resRefPath);
                    if (null == oldAsset) {
                        AnimGraphResourcesReferenceAsset resRefAsset = null;
                        AGAPublisher.ExportResourcesAsset(agaAsset.resources, ref resRefAsset);
                        AssetDatabase.CreateAsset(resRefAsset, resRefPath);
                    } else {
                        AGAPublisher.ExportResourcesAsset(agaAsset.resources, ref oldAsset);
                        EditorUtility.SetDirty(oldAsset);
                        AssetDatabase.SaveAssets();
                    }
                }
                AssetDatabase.ScheduleRefresh();
            }
        }

        bool CheckSavePath() {
            if (string.IsNullOrEmpty(savePath)) {
                var tmpPath = AnimGraphAssetsUtility.OpenSaveDialog();
                if (string.IsNullOrEmpty(tmpPath)) {
                    D.L($"不合法的保存路径： {tmpPath}");
                    return false;
                }
                savePath = tmpPath;
            }
            return true;
        }

        bool CheckPublishPath() {
            if (string.IsNullOrEmpty(publishPath)) {
                var defaultPath = Path.GetDirectoryName(savePath);
                var path = AnimGraphAssetsUtility.SelectPublishFolder(defaultPath);
                if (string.IsNullOrEmpty(path)) {
                    D.Exception($"未正确选择路径： {path}");
                    return false;
                }
                publishPath = path;
            }
            return true;
        }

        string GetFullPublishPath(string subEx, string ex = null) {
            if (ex == null) {
                ex = AGEGlobal.GetInstance().setting.GetExtensionType();
            }
            if (subEx != null) {
                return $"{publishPath}/{GetPureName()}.{subEx}.{ex}";
            } else {
                return $"{publishPath}/{GetPureName()}.{ex}";
            }
        }

        string GetPureName() {
            var defaultFileName = Path.GetFileNameWithoutExtension(savePath);
            defaultFileName = Path.GetFileNameWithoutExtension(defaultFileName); // 去除".aga"
            return defaultFileName;
        }

        byte[] SerializeArchive() {
            byte[] bytes = SerializationUtility.SerializeValue(agaRoot, DataFormat.JSON);
            return bytes;
        }

        byte[] SerializePublish(AnimGraphPublishAsset publish) {
            byte[] bytes = SerializationUtility.SerializeValue(publish, DataFormat.Binary);
            return bytes;
        }

        internal AGAHandle_Root GetRootHandle(HandleManager handleManager, CommandManager commandManager) {
            if (handleManager == null) {
                var handle1 = new AGAHandle_Root(agaRoot, null, null);
                return handle1;
            }
            var handle = handleManager.GetHandle(uuid) as AGAHandle_Root;
            if (handle != null) {
                return handle;
            }
            handle = new AGAHandle_Root(agaRoot, handleManager, commandManager);
            handleManager.AddHandle(handle);
            return handle;
        }

        internal AGA_Resources GetResources() {
            return agaAsset.resources;
        }

        internal void SetResources(List<AGA_Resources.Entry> res) {
            agaAsset.resources.entries = res;
        }

        internal string GetTimeline() {
            return agaAsset.timelineData;
        }

        internal void SetTimeline(string json) {
            agaAsset.timelineData = json;
        }

        #region 临时工具

        /// <summary>
        /// 同步aga的uuid到表层的 SO asset
        /// </summary>
        public void ReloadSOUuid() {
            agaAsset.uuid = agaRoot.uuid;
            agaAsset.graphUuid = new AUID[agaRoot.graphs.Count];
            for (int i = 0; i < agaRoot.graphs.Count; i++) {
                agaAsset.graphUuid[i] = agaRoot.graphs[i].uuid;
            }
        }

        /// <summary>
        /// 为aga文件和内部的graph重新生成新的uuid，避免复制文件后导致uuid重复
        /// </summary>
        public void ResetSOUuid() {
            agaRoot.uuid = AUIDGenerator.Gen();
            agaAsset.uuid = agaRoot.uuid;
            agaAsset.graphUuid = new AUID[agaRoot.graphs.Count];
            for (int i = 0; i < agaRoot.graphs.Count; i++) {
                agaRoot.graphs[i].uuid = AUIDGenerator.Gen();
                agaAsset.graphUuid[i] = agaRoot.graphs[i].uuid;
            }
        }


        /// <summary>
        /// 设置 formatVersion 到最新
        /// </summary>
        public void SetFormatVersion() {
            agaRoot.formatVersion = AGA_Root.usingFormatVersion;
        }

        #endregion

    }
}
